package com.telecom.restaurant.service;

import com.telecom.restaurant.constant.DefaultConstant;
import com.telecom.restaurant.dao.OrderDao;
import com.telecom.restaurant.dao.RestaurantDao;
import com.telecom.restaurant.enums.OrderStatusEnum;
import com.telecom.restaurant.exception.BizException;
import com.telecom.restaurant.model.OrderPO;
import com.telecom.restaurant.model.RestaurantPO;
import com.telecom.restaurant.model.param.OrderSearchParam;
import com.telecom.restaurant.util.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Service
public class OrderCronService {

    private Logger logger = LoggerFactory.getLogger(getClass());

    @Autowired
    private OrderDao orderDao;

    @Autowired
    private RestaurantDao restaurantDao;

    @Autowired
    private OrderService orderService;

    /**
     * 下午5点 未支付 自动关单
     */
//    @Scheduled(cron = "5 0 17 ? * MON-FRI")
    public void closeOrderEveryAfternoon() {
        Date orderDate = new Date();
        logger.info("[CRON] run closeOrderEveryAfternoon, date:{}", DateUtil.convertDate2DateString(orderDate));
        List<RestaurantPO> restaurantPOList = restaurantDao.getAll();
        for (RestaurantPO restaurant : restaurantPOList) {
            logger.info("[CRON] run closeOrderEveryAfternoon, restaurantId:{}, begin", restaurant.getId());
            int total = this.batchUpdateTodayOrder(restaurant.getId(), orderDate, OrderStatusEnum.WAIT_PAY, OrderStatusEnum.CANCEL_NOT_PAY);
            logger.info("[CRON] run closeOrderEveryAfternoon, restaurantId:{}, total:{}", restaurant.getId(), total);
        }
    }

    /**
     * 每分钟检查，半小时未支付自动关单
     */
//    @Scheduled(cron = "0 0/1 0-16 ? * MON-FRI")
    public void closeEveryMinute() {
        Date now = new Date();
        logger.info("[CRON] run closeEveryMinute , begin");
        List<RestaurantPO> restaurantPOList = restaurantDao.getAll();
        for (RestaurantPO restaurant : restaurantPOList) {
            OrderSearchParam param = new OrderSearchParam();
            param.setStatus(OrderStatusEnum.WAIT_PAY.getCode());
            param.setRestaurantId(restaurant.getId());
            param.setOrderDate(now);
            int pageNo = 1;
            while (true) {
                param.setPageNo(pageNo++);
                List<OrderPO> orderPOList = orderDao.searchOrder(param);
                if (orderPOList == null || orderPOList.isEmpty()) {
                    break;
                }

                for (OrderPO orderPO : orderPOList) {
                    if (orderPO.getOrderTime().getTime() - now.getTime() > DefaultConstant.CLOSE_ORDER_TIME) {
                        try {
                            orderService.cancelOrder(orderPO.getId(), OrderStatusEnum.CANCEL_NOT_PAY);
                        } catch (BizException bizEx) {
                            logger.error("[CRON] run closeEveryMinute,  close order failure. orderId:{}, reason:{}"
                                    , orderPO.getId(), bizEx.getDataResult());
                        }
                    }
                }
                if (orderPOList.size() < param.getPageSize()) {
                    break;
                }
            }
        }
    }

    /**
     * 每天晚上，不取餐的自动取消
     */
//    @Scheduled(cron = "0 55 23 ? * MON-FRI")
    public void cancelNotPickOrder() {
        Date orderDate = new Date();
        logger.info("[CRON] run cancelNotPickOrder, date:{}", DateUtil.convertDate2DateString(orderDate));
        // 下午5点 未支付 自动关单
        List<RestaurantPO> restaurantPOList = restaurantDao.getAll();
        for (RestaurantPO restaurant : restaurantPOList) {
            logger.info("[CRON] run cancelNotPickOrder, restaurantId:{}, begin", restaurant.getId());
            int total = batchUpdateTodayOrder(restaurant.getId(), orderDate, OrderStatusEnum.WAIT_PICK, OrderStatusEnum.PICK_OVERTIME);
            logger.info("[CRON] run cancelNotPickOrder, restaurantId:{}, total:{}", restaurant.getId(), total);
        }
    }


    /**
     * 批量修改订单状态
     *
     * @param restaurantId
     * @param orderDate
     * @param oldStatus
     * @param newStatus
     * @return
     */
    private int batchUpdateTodayOrder(Long restaurantId, Date orderDate, OrderStatusEnum oldStatus, OrderStatusEnum newStatus) {
        int total = 0;
        List<Long> orderIdList = new ArrayList<>();
        OrderSearchParam param = new OrderSearchParam();
        param.setStatus(oldStatus.getCode());
        param.setRestaurantId(restaurantId);
        param.setOrderDate(orderDate);
        int pageNo = 1;
        while (true) {
            param.setPageNo(pageNo++);
            orderIdList.clear();
            List<OrderPO> orderPOList = orderDao.searchOrder(param);
            if (orderPOList == null || orderPOList.isEmpty()) {
                break;
            }
            for (OrderPO orderPO : orderPOList) {
                orderIdList.add(orderPO.getId());
            }
            int num = orderDao.batchUpdateOrderStatus(orderIdList, newStatus.getCode(), oldStatus.getCode());
            total += num;
            if (orderPOList.size() < param.getPageSize()) {
                break;
            }
        }
        return total;
    }

}
